home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PAS_0693 / SOUNDS.PAS < prev    next >
Pascal/Delphi Source File  |  1993-06-30  |  7KB  |  191 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 323 of 374
  3. From : Steven Tallent                      1:3811/210.0         30 May 93  11:23
  4. To   : All
  5. Subj : 8-bit sound on PC spkr!
  6. ────────────────────────────────────────────────────────────────────────────────}
  7. { SOUNDS.INC  5-27-93  by Steven Tallent
  8.  
  9. This is a unit to play 8-bit raw sound files on any PC, up to 64k
  10. large.  It supports the PC speaker or a DAC (LPT1 or LPT2), although
  11. I do plan to upgrade it to support the SoundBlaster and Adlib sound
  12. cards.  It is object-oriented in nature, with one instance of a
  13. speaker defined automatically.  This unit is public domain, with
  14. code and ideas captured from this echo and Dr. Dobbs Journal.
  15.  
  16. Using the code is simple.  Just setup the the Speaker.Kind,
  17. Speaker.Silent, and Speaker.DisINT to the appropriate values, then
  18. just use the methods included.  The SoundBoard object is very
  19. flexible for your own code.
  20.  
  21. SoundBoard.Play  - Plays 8-bit music in What^ for Size length, with
  22.                    Speed milliseconds between each byte, and SampleRate
  23.                    as the sample rate (in Hz).  Speed will need to be
  24.                    changed on different computers (of course).
  25.  
  26. SoundBoard.Sound - Plays a sound at HZ Hertz, Duration in ms, on
  27.                    VOICE voice.  The code included is useable on
  28.                    the PC speaker (1 voice) or the Tandy speaker
  29.                    (3 voices!).
  30.  
  31. SoundBoard.Reset - Resets the sound board.
  32.  
  33. SoundBoard.Silent- Convenient variable that disables all PLAY and SOUND
  34.                    if set to TRUE.
  35.  
  36. SoundBoard.DisINT- Disables all interrupts (except during delays)
  37.                    while using PLAY.
  38.  
  39. This code may be freely distributed, changed, or included in your
  40. own commercial or shareware code, as long as this isn't all your code
  41. does.  This code may be included in commercial or shareware code
  42. libraries only with my permission (I'd like to see someone get some
  43. use out of it).
  44. }
  45.  
  46. Unit Sounds;
  47. Interface
  48. Type BigArray = Array[0..0] of Byte;
  49.      PBigArray= ^BigArray;
  50.      KSoundBoard = (PCspeaker, Tandy, DAC1, DAC2, AdLib, SB, SBpro, SB16);
  51.      SoundBoard = Object
  52.          Kind   : KSoundBoard;
  53.          Silent : Boolean;
  54.          DisINT : Boolean;
  55.          Procedure Play (What : PBigArray; Size : Word; Speed : Byte;
  56.                          SampleRate : Word);
  57.          Procedure Sound (Hz, Duration : Word; Voice, Volume : Byte);
  58.          Procedure Reset;
  59.          end;
  60. Var Speaker : SoundBoard;
  61.  
  62. Procedure Delay (ms : Word);
  63.  
  64. Implementation
  65.  
  66. Procedure SoundBoard.Reset;
  67. Begin
  68.   Case Kind of
  69.        PCspeaker, Tandy: Port[97] := Port[97] and $FC;
  70.        end;
  71.   end;
  72.  
  73. Procedure SoundBoard.Sound (Hz, Duration : Word; Voice, Volume : Byte);
  74. VAR Count : Word; SendByte, VoiceID : Byte;
  75. Begin
  76.   Case Kind of
  77.        PCspeaker: Begin
  78.           Count := 1193180 div Hz;
  79.           Port[97] := Port[97] or 3;
  80.           Port[67] := 182;
  81.           Port[66] := Lo(Count);
  82.           Port[66] := Hi(Count);
  83.           Delay(Duration);
  84.           Port[97] := Port[97] and $FC;
  85.           end;
  86.        Tandy: Begin
  87.           If Voice = 1 then VoiceId := 0 else
  88.              If Voice = 2 then VoiceId := 32 else
  89.                 VoiceId := 64;
  90.           Count := 111861 div Hz;
  91.           SendByte := 128 + VoiceId + (Count mod 16);
  92.           Port [$61] := $68;
  93.           Port [$C0] := SendByte;
  94.           Port [$C0] := Count div 16;
  95.           If Voice = 1 then VoiceId := 16 else
  96.              If Voice = 2 then VoiceId := 48 else
  97.                 VoiceId := 96;
  98.           SendByte := 128 + VoiceId + (15 - Volume);
  99.           Port [$61] := $68;
  100.           Port [$C0] := SendByte;
  101.           Delay(Duration);
  102.           SendByte := 128 + VoiceId + 15;
  103.           Port [$61] := $68;
  104.           Port [$C0] := SendByte;
  105.        DAC1:;
  106.        DAC2:;
  107.        AdLib:;
  108.        SB:;
  109.        SBPro:;
  110.        SB16:;
  111.   end;
  112.  
  113. Procedure SoundBoard.Play (What : PBigArray; Size : Word;
  114.     Speed : Byte; SampleRate : Word);
  115. VAR Loop : Word; Count, Data : Word;
  116. Begin
  117.   If NOT Silent then Begin
  118.      Case Kind of
  119.           PCspeaker, Tandy: Begin
  120.              Port[97] := Port[97] or 3;
  121.              Count := 1193180 div (SampleRate div 256);
  122.              For Loop := 1 to Size do Begin
  123.                  Data := Count div (What^[Loop] + 1);
  124.                  Port[67] := 182;
  125.                  Port[66] := Lo(Data);
  126.                  Port[66] := Hi(Data);
  127.                  Delay(Speed);
  128.                  If DisINT then Asm CLI end;
  129.                  end;
  130.              Port[97] := Port[97] and $FC;
  131.              end;
  132.           DAC1: For Loop := 1 to Size do Begin
  133.                     Port [$0378] := What^[Loop];
  134.                     Delay (Speed);
  135.                     If DisINT then Asm CLI end;
  136.                     end;
  137.           DAC2: For Loop := 1 to Size do Begin
  138.                     Port [$0278] := What^[Loop];
  139.                     Delay (Speed);
  140.                     If DisINT then Asm CLI end;
  141.                     end;
  142.           AdLib:;
  143.           SB:;
  144.           SBPro:;
  145.           SB16:;
  146.           end;
  147.      Asm STI end;
  148.      end;
  149.   end;
  150.  
  151. Procedure Delay (ms : Word); Assembler;
  152. ASM
  153.   STI
  154.   MOV AH, $86
  155.   MOV CX, 0
  156.   MOV DX, [ms]
  157.   INT $15
  158.   end;
  159. END.
  160.  
  161. {-----------------------------------------------------------------
  162. Here's a program that will accept three values from the command
  163. line, the file, its speed, and the sample rate, and plays it
  164. through the PC speaker.  I've tried in on WAV, VOC, SAM, and even
  165. Amiga sampled files, with no problems (limited to 64k). I've even
  166. played MOD files to hear all the sampled instruments!  This program
  167. does not strip header information, but plays it too, but I can't
  168. hear the difference on WAV and VOC files.
  169. }
  170. Program TestSnd;
  171. Uses Sounds;
  172. Var I2   : PBigArray; spd  : integer; samp : Word; res : word;
  173.     siz  : Word; s : string; f1 : file of byte; F : file;
  174. Begin
  175.   Speaker.Kind := PCspeaker;
  176.   Speaker.DisINT := True;
  177.   Speaker.Silent := False;
  178.   s := ParamStr(1);
  179.   Assign(f1,s);  {Get size of file}
  180.   Reset(f1);
  181.   Val (ParamStr(2), Spd, Res);
  182.   Val (ParamStr(3), samp, Res);
  183.   siz := FileSize(f1);
  184.   close(f1);
  185.   Assign(f,s);
  186.   Reset(f);
  187.   getmem (I2,siz);  {Allocate Memory for sound file}
  188.   BlockRead(f,I2^,siz,res);  {Load sound into Memory}
  189.   Speaker.Play (i2, siz, spd, samp);
  190.   FreeMem (I2, siz);
  191. end.